package com.amigo.online.provider.video.service.impl;

import java.math.BigDecimal;

import javax.validation.ParameterNameProvider;

import br.com.userede.erede.Environment;
import br.com.userede.erede.Store;
import br.com.userede.erede.Transaction;
import br.com.userede.erede.eRede;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.amigo.online.common.core.response.StatusCode;
import com.amigo.online.common.param.dto.pay.CreditCardPayDto;
import com.amigo.online.common.param.dto.pay.PayPromoteDto;
import com.amigo.online.common.param.result.UserInfo;
import com.amigo.online.common.param.result.order.CurrencyEnum;
import com.amigo.online.common.param.result.order.GoodsTypeEnum;
import com.amigo.online.common.param.result.order.TradeStatusEnum;
import com.amigo.online.provider.video.common.GlobalController;
import com.amigo.online.provider.video.exception.PayException;
import com.amigo.online.provider.video.mapper.PromoteMapper;
import com.amigo.online.provider.video.mapper.PromoteOrderMapper;
import com.amigo.online.provider.video.mapper.UserBalanceMapper;
import com.amigo.online.provider.video.model.entity.PromoteOrder;
import com.amigo.online.provider.video.model.entity.PromoteVideo;
import com.amigo.online.provider.video.model.entity.UserBalance;
import com.amigo.online.provider.video.service.PaymentService;
import com.amigo.online.provider.video.service.PromoteService;
import com.amigo.online.provider.video.util.OrderUtils;
import com.amigo.online.provider.video.util.PayUtil;
//import com.braintreegateway.BraintreeGateway;
//import com.braintreegateway.Environment;
//import com.braintreegateway.Result;
//import com.braintreegateway.Transaction;
import com.braintreegateway.TransactionRequest;
import com.braintreegateway.ValidationError;

import cieloecommerce.sdk.ecommerce.SaleResponse;
import cieloecommerce.sdk.ecommerce.request.CieloRequestException;

@Service
@Slf4j
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PromoteOrderMapper promoteOrderMapper;

    @Autowired
    PromoteMapper promoteMapper;

    @Autowired
    UserBalanceMapper userBalanceMapper;

    @Autowired
    PromoteService promoteService;

    @Value(value = "${merchant_id}")
    private String merchant_id;

    @Value(value = "${public_key}")
    private String public_key;

    @Value(value = "${private_key}")
    private String private_key;

//    private Environment environment = Environment.SANDBOX;

    // braintree支付
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject createOrder(PayPromoteDto dto) {
        UserInfo user = GlobalController.getNowUser();
        // 插入订单
        String order_num = OrderUtils.createPromoteOrderNumber();
        PromoteOrder promoteOrder = insertOrder(user.getId(), dto.getPay_money(), order_num, dto.getPayway());

//         使用userede付钱
//        Result<Transaction> result = pay(dto.getPay_money(), dto.getNonce());
//        JSONObject payResult = payResult(result);
        JSONObject payResult = null;
        String trade_status = (String) payResult.get("trade_status");
        String transaction_id = (String) payResult.get("transaction_id");
        String errorString = (String) payResult.get("errorString");
        Long pay_time = (Long) payResult.get("pay_time");

        // 更新订单状态
        updateOrderStatus(promoteOrder.getId(), trade_status, transaction_id, errorString, pay_time);

        // 创建速推视频
        PromoteVideo promoteVideo = new PromoteVideo();
        BeanUtils.copyProperties(dto, promoteVideo);
        insertPromoteVideo(user.getId(), promoteOrder.getId(), dto.getPay_money(), dto.getPormote_money(), trade_status,
                promoteVideo, dto.getType());

        // 创建账户余额，有则更新，无则插入
        if (StringUtils.equals(trade_status, TradeStatusEnum.success.name())) {
            createOrUpdateBalance(user.getId(), dto.getPay_money());
        }

        JSONObject res = new JSONObject();
        res.put("order_num", order_num);
        res.put("order_id", promoteOrder.getId());
        res.put("pay_time", pay_time);
        res.put("trade_status", trade_status);
        res.put("money", dto.getPay_money());
        return res;
    }

    @Override
    public String getClientoken() {
        return null;
    }

    // braintree重新支付
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject repay(PayPromoteDto dto) {
        UserInfo user = GlobalController.getNowUser();
        PromoteOrder promoteOrder = promoteOrderMapper.selectByPrimaryKey(dto.getOrder_id());
        if (!checkRepayForm(dto.getOrder_num(), dto.getPay_money(), dto.getPay_time(), dto.getOrder_id(),
                dto.getTrade_status(), promoteOrder)) {
            throw new PayException(StatusCode.PAY_ILLEGAL_OPERATION);
        }
        // 使用braintree付钱
//        Result<Transaction> result = pay(dto.getPay_money(), dto.getNonce());
//        JSONObject payResult = payResult(result);
        JSONObject payResult = null;
        String trade_status = (String) payResult.get("trade_status");
        String transaction_id = (String) payResult.get("transaction_id");
        String errorString = (String) payResult.get("errorString");
        Long repay_time = (Long) payResult.get("pay_time");

        // 更新订单状态
        updateOrderStatus(promoteOrder.getId(), trade_status, transaction_id, errorString, repay_time);

        // 更新速推视频状态
        updatePromoteVideoStatus(dto.getOrder_id(), trade_status);

        if (StringUtils.equals(trade_status, TradeStatusEnum.success.name())) {
            // 创建账户余额，有则更新，无则插入
            createOrUpdateBalance(user.getId(), dto.getPay_money());

        }

        JSONObject res = new JSONObject();
        res.put("order_num", promoteOrder.getTrade_num());
        res.put("order_id", promoteOrder.getId());
        res.put("pay_time", dto.getPay_time());
        res.put("trade_status", trade_status);
        res.put("money", promoteOrder.getMoney());
        return res;
    }

    // 信用卡支付
    @Override
    public JSONObject creditCardPay(CreditCardPayDto dto) {
        UserInfo user = GlobalController.getNowUser();
        // 插入订单
        String order_num = OrderUtils.createPromoteOrderNumber();

        PromoteOrder order = new PromoteOrder();
        order.setUser_id(user.getId());
        order.setPayway(dto.getPayway());
        order.setMoney(dto.getPay_money());
        order.setTrade_num(order_num);
        order.setCreated_time(System.currentTimeMillis() / 1000);
        order.setCurrency(CurrencyEnum.BRL.name());
        order.setGoods_name(GoodsTypeEnum.adv.name());
        order.setCardNo(dto.getCard_number());
        order.setCardOwner(dto.getHolder());
        order.setCardSafeCode("xxx");
        order.setCardValidPeriod(dto.getExpiration_date());
        order.setInvoiceAddress(dto.getInvoiceAddress());
        order.setInvoiceConsignee(dto.getInvoiceConsignee());
        order.setInvoiceTelphone(dto.getInvoiceTelphone());
        order.setTrade_time(order.getCreated_time());
        promoteOrderMapper.insertSelective(order);
        dto.setOrder_num(order_num);
        //PromoteOrder promoteOrder = insertOrder(user.getId(), dto.getPay_money(), order_num, dto.getPayway());

//        String trade_status = null;
//        String transaction_id = null;
//        String errorString = null;
        Long pay_time = System.currentTimeMillis() / 1000;
        JSONObject res = null;
        // 使用信用卡支付;
        try {
//            SaleResponse saleResponse = PayUtil.creditCardPay(order_num, dto.getPay_money(), dto.getPin(),
//                    dto.getCards(), dto.getExpiration_date(), dto.getCard_number(), dto.getHolder());
//            if (saleResponse != null && StringUtils.equals(saleResponse.getStatus(), "2")) {
//                trade_status = TradeStatusEnum.success.name();
//                transaction_id = saleResponse.getMerchantOrderId();
//            }
            res = payWithCard(dto);
            pay_time = System.currentTimeMillis()/1000 - pay_time;
//        } catch (Exception e) {
//            trade_status = TradeStatusEnum.failure.name();
////            errorString = e.getError().getCode() + " | " + e.getError().getMessage();
//            e.printStackTrace();
        } catch (Exception e) {
//            res.getString("trade_status") = TradeStatusEnum.failure.name();
//            errorString = "其他异常";
            e.printStackTrace();
        }
        updateOrderStatus(order.getId(), res.getString("trade_status"), res.getString("transaction_id"), res.getString("errInfo"), pay_time);

        // 创建速推视频
        PromoteVideo promoteVideo = new PromoteVideo();
        BeanUtils.copyProperties(dto, promoteVideo);
        insertPromoteVideo(user.getId(), order.getId(), dto.getPay_money(), dto.getPormote_money(), res.getString("trade_status"),
                promoteVideo, dto.getType());

        // 创建账户余额，有则更新，无则插入
        if (StringUtils.equals(res.getString("trade_status"), TradeStatusEnum.success.name())) {
            createOrUpdateBalance(user.getId(), dto.getPay_money());
        }

        JSONObject res1 = new JSONObject();
        res1.put("order_num", order_num);
        res1.put("order_id", order.getId());
        res1.put("pay_time", pay_time);
        res1.put("trade_status", res.getString("trade_status"));
        res1.put("money", dto.getPay_money());
        return res1;
    }

    // 信用卡重新支付
    @Override
    public JSONObject reCreditCardPay(CreditCardPayDto dto) {
        UserInfo user = GlobalController.getNowUser();
        PromoteOrder promoteOrder = promoteOrderMapper.selectByPrimaryKey(dto.getOrder_id());
        if (!checkRepayForm(dto.getOrder_num(), dto.getPay_money(), dto.getPay_time(), dto.getOrder_id(),
                dto.getTrade_status(), promoteOrder)) {
            throw new PayException(StatusCode.PAY_ILLEGAL_OPERATION);
        }
//        String trade_status = null;
//        String transaction_id = null;
//        String errorString = null;
        Long pay_time = System.currentTimeMillis() / 1000;
        JSONObject res = null;
        // 使用信用卡支付
        try {
//            SaleResponse saleResponse = PayUtil.creditCardPay(dto.getOrder_num(), dto.getPay_money(), dto.getPin(),
//                    dto.getCards(), dto.getExpiration_date(), dto.getCard_number(), dto.getHolder());
//            if (saleResponse != null && StringUtils.equals(saleResponse.getStatus(), "2")) {
//                trade_status = TradeStatusEnum.success.name();
//            }
//        } catch (CieloRequestException e) {
//            trade_status = TradeStatusEnum.failure.name();
//            errorString = e.getError().getCode() + " | " + e.getError().getMessage();
//            e.printStackTrace();
            res = payWithCard(dto);
            pay_time = System.currentTimeMillis()/1000;

        } catch (Exception e) {
//            trade_status = TradeStatusEnum.failure.name();
//            errorString = "其他异常";
            e.printStackTrace();
        }

        // 更新订单状态
        updateOrderStatus(promoteOrder.getId(), res.getString("trade_status"), res.getString("transaction_id"), res.getString("errInfo"), pay_time);

        // 更新速推视频状态
        updatePromoteVideoStatus(dto.getOrder_id(), res.getString("trade_status"));

        if (StringUtils.equals(res.getString("trade_status"), TradeStatusEnum.success.name())) {
            // 创建账户余额，有则更新，无则插入
            createOrUpdateBalance(user.getId(), dto.getPay_money());
        }

        JSONObject res1 = new JSONObject();
        res1.put("order_num", dto.getOrder_num());
        res1.put("order_id", promoteOrder.getId());
        res1.put("pay_time", pay_time);
        res1.put("trade_status", res.getString("trade_status"));
        res1.put("money", dto.getPay_money());
        return res1;
    }

    private void updatePromoteVideoStatus(Long order_id, String trade_status) {
        PromoteVideo promoteVideo = new PromoteVideo();
        promoteVideo.setStatus(TradeStatusEnum.success.name().equals(trade_status) ? 1 : 3);
        promoteVideo.setOrder_id(order_id);
        promoteMapper.updatePormoteVideoStatus(promoteVideo);
    }

    private void insertPromoteVideo(Long user_id, Long order_id, Integer pay_money, Integer promote_money,
                                    String trade_status, PromoteVideo promoteVideo, Integer type) {
        promoteVideo.setOrder_id(order_id);
        promoteVideo.setUser_id(user_id);
        promoteVideo.setBalance(promote_money);
        promoteVideo.setMoney(promote_money);
        promoteVideo.setActual_money(pay_money);
        promoteVideo.setExpected_play_amount(promoteService.getExpectedViewAmount(promote_money, type));
        promoteVideo.setCreatedTime(System.currentTimeMillis() / 1000);
        promoteVideo.setStatus(TradeStatusEnum.success.name().equals(trade_status) ? 1 : 3); // 1-投放中 2-已结束 3-支付失败
        promoteMapper.insertSelective(promoteVideo);
    }

    private void updateOrderStatus(Long order_id, String trade_status, String transaction_id, String errorString,
                                   Long pay_time) {
        PromoteOrder updateOrder = new PromoteOrder();
        updateOrder.setId(order_id);
        updateOrder.setTrade_status(trade_status);
        updateOrder.setTransaction_id(transaction_id);
        updateOrder.setTrade_time(pay_time);
        updateOrder.setErr_callback(errorString);
        promoteOrderMapper.updateOrderStatus(updateOrder);
    }


    public JSONObject payWithCard(CreditCardPayDto dto) {

        String errInfo = "";
        String errCode = "";
        boolean paySuccess = false;
        Long payTime = 0L;
        String transactionId = dto.getOrder_num();

        JSONObject result = new JSONObject();

        Store store = new Store("80749690", "b183a01cef7647349e952fb4b9c6f039", Environment.production());

        Transaction transaction = new Transaction(Integer.valueOf(String.valueOf(dto.getPay_money())), dto.getOrder_num());
        try {
//            if(card.getCardType() == 1) {
                log.info("信用卡支付--->");
                log.info(dto.getCard_number());
                log.info(dto.getPin());
                log.info(dto.getExpiration_date().split("/")[0]);
                log.info(dto.getExpiration_date().split("/")[1]);
                log.info(dto.getHolder());
                log.info("金额 -> "+dto.getPay_money());
                log.info("订单号->"+dto.getOrder_num());
                transaction.creditCard(
                        dto.getCard_number(),
                        dto.getPin(),
                        dto.getExpiration_date().split("/")[0],
                        dto.getExpiration_date().split("/")[1],
                        dto.getHolder().trim()
                );
                transaction = (new eRede(store).create(transaction));
//            }else {
//                logger.info("储蓄卡支付--->");
//                logger.info(card.getCardNo());
//                logger.info(card.getCardSafeCode());
//                logger.info(card.getCardValidPeriod().split("/")[0]);
//                logger.info(card.getCardValidPeriod().split("/")[1]);
//                logger.info(card.getCardOwner());
//                logger.info("金额 -> "+actualPayAmount);
//                logger.info("订单号->"+orderNo);
//                transaction.debitCard(
//                        card.getCardNo(),
//                        card.getCardSafeCode(),
//                        card.getCardValidPeriod().split("/")[0],
//                        card.getCardValidPeriod().split("/")[1],
//                        card.getCardOwner()
//                );
//                transaction = (new eRede(store).create(transaction));
//            }
            if (transaction.getReturnCode().equals("00")) {
                paySuccess = true;
                transactionId = dto.getOrder_num();
                payTime = System.currentTimeMillis()/1000;
            }else {
                transactionId = dto.getOrder_num();
                payTime = System.currentTimeMillis()/1000;
            }
        } catch (Exception e) {
            log.info("支付失败");
            paySuccess = false;
            if(transaction != null) {
                log.info(transaction.getReturnCode());
            }
            e.printStackTrace();
        }catch(Throwable t) {
            paySuccess = false;
        } finally {
            result.put("success", paySuccess);
            result.put("errInfo", errInfo);
            result.put("payTime", payTime);
            result.put("errCode", errCode);
            result.put("transactionId", transactionId);
            if(paySuccess == true)
            result.put("trade_status","success");
            else
                result.put("trade_status","failure");
        }
        return result;
    }

//    @Transactional(rollbackFor = Exception.class)
//    private Result<Transaction> pay(Integer money, String nonce) {
//        BigDecimal decimalAmount = new BigDecimal(money).divide(new BigDecimal(100));// dto.getPay_money()的单位是分
//        // BigDecimal decimalAmount = new BigDecimal(2000.00);
//        TransactionRequest request = new TransactionRequest().amount(decimalAmount).paymentMethodNonce(nonce).options()
//                .submitForSettlement(true).done();
////        BraintreeGateway gateway = new BraintreeGateway(environment, merchant_id, public_key, private_key);
//        Result<Transaction> result = gateway.transaction().sale(request);
//        return result;
//    }

//    @Transactional(rollbackFor = Exception.class)
//    private JSONObject payResult(Result<Transaction> result) {
//        String trade_status = null;
//        String transaction_id = null;
//        String errorString = null;
//        Long pay_time = null;
//        if (result.isSuccess()) {
//            trade_status = TradeStatusEnum.success.name();
//            transaction_id = result.getTarget().getId();
//            pay_time = result.getTarget().getCreatedAt().getTimeInMillis() / 1000;
//        } else if (result.getTransaction() != null) {
//            trade_status = TradeStatusEnum.failure.name();
//            transaction_id = result.getTransaction().getId();
//            pay_time = result.getTransaction().getCreatedAt().getTimeInMillis() / 1000;
//        } else {
//            trade_status = TradeStatusEnum.failure.name();
//            pay_time = System.currentTimeMillis() / 1000;
//            for (ValidationError error : result.getErrors().getAllDeepValidationErrors()) {
//                errorString += "Error: " + error.getCode() + ": " + error.getMessage() + "\n";
//            }
//            log.error("errorDetails:{}", errorString);
//        }
//        System.out.println("trade_status:" + trade_status);
//        System.out.println("transaction_id:" + transaction_id);
//        System.out.println("errorString:" + errorString);
//        JSONObject payResult = new JSONObject();
//        payResult.put("trade_status", trade_status);
//        payResult.put("transaction_id", transaction_id);
//        payResult.put("errorString", errorString);
//        payResult.put("pay_time", pay_time);
//        return payResult;
//    }

    @Transactional(rollbackFor = Exception.class)
     PromoteOrder insertOrder(Long user_id, Integer money, String order_num, String payway) {
        PromoteOrder record = new PromoteOrder();
        record.setCurrency(CurrencyEnum.BRL.name());
        record.setGoods_name(GoodsTypeEnum.adv.name());
        record.setMoney(money);
        record.setUser_id(user_id);
        record.setTrade_num(order_num);
        record.setPayway(payway);
        record.setCreated_time(System.currentTimeMillis() / 1000);
        promoteOrderMapper.insertSelective(record);
        return record;
    }

//    public String getClientoken() {
//        BraintreeGateway gateway = new BraintreeGateway(environment, merchant_id, public_key, private_key);
//        System.out.println("拿取了token");
//        return gateway.clientToken().generate();
//    }

    @Transactional(rollbackFor = Exception.class)
     boolean checkRepayForm(String order_num, Integer pay_money, Long pay_time, Long order_id,
                                   String trade_status, PromoteOrder promoteOrder) {
        long currentTime = System.currentTimeMillis() / 1000;
        if (pay_time < currentTime - 30 * 60) { // 重新支付时间超过了30min
            throw new PayException(StatusCode.PAY_TIMEOUT_30MIN);
        }
        System.out.println(promoteOrder.getTrade_num() + "<--->" + order_num);
        System.out.println(promoteOrder.getMoney() + "<--->" + pay_money);
        System.out.println(promoteOrder.getTrade_time() + "<--->" + pay_time);
        System.out.println(promoteOrder.getId() + "<--->" + order_id);
        System.out.println(promoteOrder.getTrade_status() + "<--->" + trade_status);

        return StringUtils.equals(promoteOrder.getTrade_num(), order_num) && promoteOrder.getMoney().equals(pay_money)
                && promoteOrder.getTrade_time().equals(pay_time) && promoteOrder.getId().equals(order_id)
                && StringUtils.equals(promoteOrder.getTrade_status(), trade_status);
    }

    @Transactional(rollbackFor = Exception.class)
     void createOrUpdateBalance(Long user_id, Integer pay_money) {
        UserBalance query = new UserBalance();
        query.setUser_id(user_id);
        userBalanceMapper.selectCount(query);
        Long ct = System.currentTimeMillis() / 1000;
        if (userBalanceMapper.selectCount(query) > 0) {
            userBalanceMapper.updateAddBalance(user_id, pay_money, ct);
        } else {
            UserBalance userBalance = new UserBalance();
            userBalance.setBalance(pay_money);
            userBalance.setUser_id(user_id);
            userBalance.setCreatedTime(ct);
            userBalanceMapper.insertSelective(userBalance);
        }
    }

}
